export type SelectedElementInfo = {
  tagName: string;
  id?: string;
  classList?: string[];
  text?: string;
  href?: string;
  src?: string;
  cssSelector?: string;
  xpath?: string;
  rect?: { top: number; left: number; width: number; height: number };
  outerHTML?: string;
};

export type IframeVisualEditor = {
  enable: () => void;
  disable: () => void;
  clearSelection: () => void;
  unselect: (selector: string) => void;
  dispose: () => void;
};

export function createIframeVisualEditor(
  iframeEl: HTMLIFrameElement,
  options?: {
    onSelect?: (info: SelectedElementInfo) => void;
    onHover?: (info: SelectedElementInfo | null) => void;
    onUnselect?: (selector: string) => void;
    onReady?: () => void;
    targetOrigin?: string;
  }
): IframeVisualEditor {
  const targetOrigin = options?.targetOrigin ?? '*';

  const handleMessage = (e: MessageEvent) => {
    if (!iframeEl.contentWindow || e.source !== iframeEl.contentWindow) return;
    const data = e.data;
    if (!data || typeof data !== 'object') return;
    if (data.type === 'VISUAL_EDIT_HOVER') {
      options?.onHover?.(data.payload || null);
    } else if (data.type === 'VISUAL_EDIT_SELECT') {
      options?.onSelect?.(data.payload);
    } else if (data.type === 'VISUAL_EDIT_UNSELECT') {
      if (data.payload && data.payload.selector) options?.onUnselect?.(data.payload.selector);
    } else if (data.type === 'VISUAL_EDIT_READY') {
      options?.onReady?.();
    }
  };

  window.addEventListener('message', handleMessage);

  const injectScript = () => {
    try {
      const doc = iframeEl.contentDocument;
      const win = iframeEl.contentWindow;
      if (!doc || !win) return;
      if ((win as any) && (win as any).__VISUAL_EDITOR__) return;

      const script = doc.createElement('script');
      script.type = 'text/javascript';
      script.text = `(function(){
  if (window.__VISUAL_EDITOR__) return;
  var STATE = { enabled: false, hoverOverlay: null, selectOverlays: [], selectedEls: [] };
  var MAX_TEXT_LEN = 120;

  function ensureHoverOverlay(){
    var doc = document;
    if (!STATE.hoverOverlay) {
      var d = doc.createElement('div');
      d.style.position = 'absolute';
      d.style.border = '2px dashed #1677ff';
      d.style.pointerEvents = 'none';
      d.style.zIndex = '2147483647';
      d.style.display = 'none';
      d.className = 've-hover-overlay';
      doc.body.appendChild(d);
      STATE.hoverOverlay = d;
    }
  }

  function createSelectOverlay(){
    var d = document.createElement('div');
    d.style.position = 'absolute';
    d.style.border = '2px solid #fa541c';
    d.style.pointerEvents = 'none';
    d.style.zIndex = '2147483647';
    d.style.display = 'block';
    d.className = 've-select-overlay';
    document.body.appendChild(d);
    return d;
  }

  function createCloseBtn(){
    var b = document.createElement('div');
    b.className = 've-close-btn';
    b.textContent = '×';
    b.style.position = 'absolute';
    b.style.width = '18px';
    b.style.height = '18px';
    b.style.lineHeight = '18px';
    b.style.textAlign = 'center';
    b.style.background = '#ff4d4f';
    b.style.color = '#fff';
    b.style.borderRadius = '50%';
    b.style.boxShadow = '0 0 0 2px #fff';
    b.style.cursor = 'pointer';
    b.style.zIndex = '2147483647';
    document.body.appendChild(b);
    return b;
  }

  function updateBounds(el, overlay, btn){
    if (!el) return;
    var rect = el.getBoundingClientRect();
    if (overlay){
      overlay.style.top = (rect.top + window.scrollY) + 'px';
      overlay.style.left = (rect.left + window.scrollX) + 'px';
      overlay.style.width = rect.width + 'px';
      overlay.style.height = rect.height + 'px';
      overlay.style.display = 'block';
    }
    if (btn){
      var top = rect.top + window.scrollY - 9; // 稍微偏上
      var left = rect.left + window.scrollX + rect.width - 9; // 右上角
      btn.style.top = top + 'px';
      btn.style.left = left + 'px';
      btn.style.display = 'block';
    }
  }

  function hide(el){ if (el) el.style.display = 'none'; }

  function buildCssSelector(el){
    if (!(el && el.nodeType === 1)) return '';
    var parts = [];
    var cur = el;
    var safety = 0;
    while (cur && cur.nodeType === 1 && parts.length < 5 && safety++ < 50) {
      var selector = cur.nodeName.toLowerCase();
      if (cur.id) {
        selector += '#' + (window.CSS && CSS.escape ? CSS.escape(cur.id) : cur.id.replace(/\s/g, '-'));
        parts.unshift(selector);
        break;
      } else {
        var cls = (cur.className || '').toString().trim();
        if (cls) {
          var classes = cls.split(/\s+/).slice(0, 3).map(function(c){ return '.' + (window.CSS && CSS.escape ? CSS.escape(c) : c.replace(/[^a-zA-Z0-9_-]/g, '')); }).join('');
          selector += classes;
        }
        var sibling = cur.parentNode && cur.parentNode.children ? Array.prototype.slice.call(cur.parentNode.children) : [];
        var index = sibling.indexOf ? sibling.indexOf(cur) : Array.prototype.indexOf.call(sibling, cur);
        selector += ':nth-child(' + (index + 1) + ')';
      }
      parts.unshift(selector);
      cur = cur.parentElement;
    }
    return parts.join(' > ');
  }

  function buildXPath(el){
    if (!(el && el.nodeType === 1)) return '';
    if (el.id) { return '//*[@id="' + String(el.id).replace(/\"/g, '\\"') + '"]'; }
    var parent = el.parentNode;
    var tag = el.nodeName.toLowerCase();
    var index = 1;
    if (parent) {
      var children = parent.childNodes;
      for (var i = 0; i < children.length; i++) {
        var sib = children[i];
        if (sib === el) break;
        if (sib.nodeType === 1 && sib.nodeName === el.nodeName) index++;
      }
      return (parent.nodeType === 1 ? buildXPath(parent) : '') + '/' + tag + '[' + index + ']';
    }
    return '/' + tag + '[' + index + ']';
  }

  function extractInfo(el){
    if (!(el && el.nodeType === 1)) return null;
    var tagName = el.tagName.toLowerCase();
    var id = el.id || undefined;
    var classList = Array.prototype.slice.call(el.classList || []);
    var textRaw = (el.innerText || el.textContent || '');
    var text = textRaw.trim().replace(/\s+/g, ' ').slice(0, MAX_TEXT_LEN);
    var tag = el.tagName;
    var href = tag === 'A' ? (el.href || el.getAttribute('href') || undefined) : undefined;
    var src;
    if (tag === 'IMG' || tag === 'VIDEO' || tag === 'AUDIO') {
      src = el.getAttribute('src') || el['src'] || undefined;
    }
    var rect = el.getBoundingClientRect();
    return {
      tagName: tagName,
      id: id,
      classList: classList,
      text: text,
      href: href,
      src: src,
      cssSelector: buildCssSelector(el),
      xpath: buildXPath(el),
      rect: { top: rect.top + window.scrollY, left: rect.left + window.scrollX, width: rect.width, height: rect.height },
      outerHTML: el.outerHTML
    };
  }

  function onMouseMove(e){
    if (!STATE.enabled) return;
    var target = e.target;
    if (!target || target === document.body || target === document.documentElement) {
      hide(STATE.hoverOverlay);
      try { window.parent.postMessage({ type: 'VISUAL_EDIT_HOVER', payload: null }, '*'); } catch (err) {}
      return;
    }
    ensureHoverOverlay();
    updateBounds(target, STATE.hoverOverlay, null);
    var info = extractInfo(target);
    try { window.parent.postMessage({ type: 'VISUAL_EDIT_HOVER', payload: info }, '*'); } catch (err) {}
  }

  function addSelect(el){
    // 去重
    for (var i=0;i<STATE.selectedEls.length;i++){ if (STATE.selectedEls[i] === el) return; }
    var overlay = createSelectOverlay();
    var closeBtn = createCloseBtn();
    var selector = buildCssSelector(el);
    STATE.selectedEls.push(el);
    STATE.selectOverlays.push({ el: el, overlay: overlay, close: closeBtn, selector: selector });
    updateBounds(el, overlay, closeBtn);
    closeBtn.addEventListener('click', function(ev){
      ev.preventDefault(); ev.stopPropagation();
      removeSelectBySelector(selector, true);
    }, true);
    var info = extractInfo(el);
    try { window.parent.postMessage({ type: 'VISUAL_EDIT_SELECT', payload: info }, '*'); } catch (err) {}
  }

  function removeSelectBySelector(selector, notify){
    if (!selector) return;
    for (var i = STATE.selectOverlays.length - 1; i >= 0; i--) {
      var item = STATE.selectOverlays[i];
      if (item.selector === selector) {
        if (item.overlay && item.overlay.parentNode) item.overlay.parentNode.removeChild(item.overlay);
        if (item.close && item.close.parentNode) item.close.parentNode.removeChild(item.close);
        STATE.selectOverlays.splice(i, 1);
        var idx = STATE.selectedEls.indexOf(item.el);
        if (idx >= 0) STATE.selectedEls.splice(idx, 1);
        if (notify) {
          try { window.parent.postMessage({ type: 'VISUAL_EDIT_UNSELECT', payload: { selector: selector } }, '*'); } catch (e) {}
        }
      }
    }
  }

  function clearAll(){
    hide(STATE.hoverOverlay);
    for (var i=0;i<STATE.selectOverlays.length;i++){
      var it = STATE.selectOverlays[i];
      if (it.overlay && it.overlay.parentNode) it.overlay.parentNode.removeChild(it.overlay);
      if (it.close && it.close.parentNode) it.close.parentNode.removeChild(it.close);
    }
    STATE.selectOverlays = [];
    STATE.selectedEls = [];
  }

  function onClick(e){
    if (!STATE.enabled) return;
    e.preventDefault();
    e.stopPropagation();
    var target = e.target;
    if (!target || target === document.body || target === document.documentElement) return;
    // 忽略点到编辑器内部元素（关闭按钮、覆盖层）
    var cls = (target.className || '').toString();
    if (cls.indexOf('ve-close-btn') >= 0 || cls.indexOf('ve-hover-overlay') >= 0 || cls.indexOf('ve-select-overlay') >= 0) {
      return;
    }
    addSelect(target);
  }

  function onScrollOrResize(){
    if (!STATE.enabled) return;
    for (var i=0;i<STATE.selectOverlays.length;i++){
      var it = STATE.selectOverlays[i];
      updateBounds(it.el, it.overlay, it.close);
    }
  }

  function start(){
    if (STATE.enabled) return;
    STATE.enabled = true;
    ensureHoverOverlay();
    document.addEventListener('mousemove', onMouseMove, true);
    document.addEventListener('click', onClick, true);
    window.addEventListener('scroll', onScrollOrResize, true);
    window.addEventListener('resize', onScrollOrResize, true);
    try { window.parent.postMessage({ type: 'VISUAL_EDIT_READY' }, '*'); } catch (e) {}
  }

  function stop(){
    STATE.enabled = false;
    document.removeEventListener('mousemove', onMouseMove, true);
    document.removeEventListener('click', onClick, true);
    window.removeEventListener('scroll', onScrollOrResize, true);
    window.removeEventListener('resize', onScrollOrResize, true);
    hide(STATE.hoverOverlay);
  }

  window.addEventListener('message', function(e){
    var data = e.data;
    if (!data || typeof data !== 'object') return;
    if (data.type === 'VISUAL_EDIT_CMD') {
      var cmd = data.payload;
      if (cmd === 'start' || (cmd && cmd.action === 'start')) start();
      else if (cmd === 'stop' || (cmd && cmd.action === 'stop')) stop();
      else if (cmd === 'clear' || (cmd && cmd.action === 'clear')) clearAll();
      else if (cmd && cmd.action === 'unselect' && cmd.selector) removeSelectBySelector(cmd.selector, false);
    }
  });

  window.__VISUAL_EDITOR__ = { start: start, stop: stop, clearSelection: clearAll };
})();`;
      (doc.head || doc.body || doc.documentElement).appendChild(script);
    } catch (e) {
      // ignore
    }
  };

  const postCmd = (payload: any) => {
    try {
      iframeEl.contentWindow?.postMessage({ type: 'VISUAL_EDIT_CMD', payload }, targetOrigin);
    } catch (e) {
      // ignore
    }
  };

  const ensureReady = (cb: () => void) => {
    const tryRun = () => {
      if (iframeEl.contentDocument && iframeEl.contentWindow) {
        cb();
      } else {
        setTimeout(tryRun, 50);
      }
    };
    const isLoaded = () => {
      try {
        const d = iframeEl.contentDocument as Document | null;
        return !!d && d.readyState !== 'loading';
      } catch { return false; }
    };
    if (isLoaded()) tryRun();
    else iframeEl.addEventListener('load', tryRun, { once: true });
  };

  const enable = () => {
    ensureReady(() => {
      injectScript();
      try {
        const api = (iframeEl.contentWindow as any)?.__VISUAL_EDITOR__;
        if (api && typeof api.start === 'function') {
          api.start();
          return;
        }
      } catch (_) {}
      postCmd('start');
    });
  };

  const disable = () => {
    try {
      const api = (iframeEl.contentWindow as any)?.__VISUAL_EDITOR__;
      if (api && typeof api.stop === 'function') {
        api.stop();
      } else {
        postCmd('stop');
      }
    } catch (_) {
      postCmd('stop');
    }
  };

  const clearSelection = () => {
    try {
      const api = (iframeEl.contentWindow as any)?.__VISUAL_EDITOR__;
      if (api && typeof api.clearSelection === 'function') {
        api.clearSelection();
      } else {
        postCmd('clear');
      }
    } catch (_) {
      postCmd('clear');
    }
  };

  const unselect = (selector: string) => {
    postCmd({ action: 'unselect', selector });
  };

  const dispose = () => {
    window.removeEventListener('message', handleMessage);
  };

  return { enable, disable, clearSelection, unselect, dispose };
} 